liblfds release 6.0.0 release note

Release date : 18th December 2012

What's New?

  1. Moved into the "lfds600_" namespace.
  2. Absolutely NO OTHER CHANGES.

    This release is a stepping-stone from 6, which has no namespace, to the new namespace policy.

Known Issues

  1. The test and benchmark program offers an iteration argument, for running tests multiple times; in fact, this is bugged, and will crash on the second iteration. The problem is use of static variables in the tests, which don't get reset to 0 and so cause memory exceptions (it worked on x64!).
  2. liblfds does not in fact support IA64. I had thought there was a compiler environment bug of some kind which affected this build, but it turns out to be a mistake on my part; IA64 does not in fact support contigious double-word compare-and-swap.
  3. In the slist test (/test/src/lfds600_test_slist.c) there is a missing check for NULL on line 444, which is part of the core of the traverser thread, a test thread which simply constantly loops over a list. The code looks like this;
    if( !(iteration % stss->iteration_modulo) )
    {
      lfds600_slist_get_next( se, &se );
      count++;
    }

    It should look like this;

    if( se != NULL and !(iteration % stss->iteration_modulo) )
    {
      lfds600_slist_get_next( se, &se );
      count++;
    }

    This result of this is the existence of a race condition. Some slist tests all basically work by generating list elements on the fly and while having a traverser thread running. If however the traverser thread begins to run before any elements have been generated, the missing check for NULL will permit slist_get_next() to execute on a NULL element which causes an assert.

    The following tests are affected;

    4. one head writer and one list traverser per CPU
    5. make one element, then one after writer and one list traverser per CPU
    12. one head writer, one after writer, one traverser and one 25%% deleter-traverser per CPU

  4. The freelist popping test is bugged. A variable, count, is declared as unsigned int when in fact it needs to be atom_t. The consequence is that on 64-bit platforms where unsigned int is 32 bit and pointers are 64 bit, the freelist test will report missing elements.

    The problem code is in /test/src/lfds600_test_freelist.c, line 32.

    The code looks like this;

    unsigned int
      loop,
      cpu_count,
      count;

    It should look like this;

    unsigned int
      loop,
      cpu_count;
    
    lfds600_atom_t
      count;
  5. The freelist pushing test is bugged. The test allocates (one million / number cores) freelist elements per thread. Now, with integer division, on a (for example) 24 core machine, this gives (1,000,000 / 24) = 41,666 elements per thread. However, after the test has run, there is a check that there are in *exactly* 1,000,000 elements now present in the destination freelist. This fails, because 41,666 * 24 = 999,984. The error seen is that the freelist is missing elements.
  6. The library does not use memory barriers correctly. The main upshot of this is that the queue can be corrupted; a missing barrier means that the queue can be misled about its state during enqueuing or dequeuing and as such attempt to perform the wrong action (both of those operations operate in different ways depending on the current internal state of the queue). How likely this is to happen is not clear; the window is a few instructions in length (e.g. short), it can only happen when multiple cores are using one queue, it is more likely the more busy the queue is (both in terms of number of cores using the queue and the frequency of enqueuing and dequeuing), but on my test systems, which include a 16 core, 2 NUMA node machine, I have yet to see errors even with all cores busy-using the queue (which may mean the tests are no good, at least for this problem - they certainly detected enough errors during development and testing).
  7. When built as a DLL, the abstraction API is not exported nor is the rinbuffer query function. The absence of the abstraction API do not prevent end-user use (these functions are never called directly by the user) but their absence does prevent the test programme from being able to build and run against the DLL build of liblfds. The absence of the ringbuffer query function is an end-user visible bug, since users should be able to call this function.
  8. With more modern GCC versions (the issue was found with 4.6.2) the shared object build on x86 runs out of registers when trying to assemble the in-line assembly code for contigious double-word compare-and-swap. Release builds still compile.